/**************************************************************************//**
 * @item     CosyOS-II Port
 * @file     port_cmx.h
 * @brief    CMSIS Cortex-M Core Port File
 * @author   迟凯峰
 * @version  V3.4.0
 * @date     2025.01.06
 ******************************************************************************/

#ifndef __PORT_CMX_H
#define __PORT_CMX_H

/* Header */
#include <string.h>
#include <stdbool.h>
#include "..\System\os_base.h"
#include "..\Config\mcucfg_cmx.h"

/* Memory */
#define _SYS_MEM_
#define _CODE_MEM_
#define _CONST_MEM_
#define _STACK_MEM_
#define _XDATA_MEM_
#define _STATIC_MEM_
#define _MALLOC_MEM_
#define _OBJ_MEM_
#define _RTC_MEM_
#define _TQUE_MEM_
#define _DEBUG_MEM_

/* Register */
#define _SYS_REG_

/* Typedef */
#define m_boolvoid_tf *(s_boolvoid_tfp)
typedef unsigned long long int s_u64_t;
typedef bool     m_bit_t;
typedef s_u32_t  m_sp_t;
typedef s_u32_t  m_stacksize_t;
typedef s_u32_t  m_tick_t;
typedef s_u32_t  m_pc_t;
typedef s_u32_t  m_taskmsg_t;
typedef s_u32_t  m_fetion_t;
typedef s_u32_t  m_group_t;

/* Extern */
extern  s_u32_t  m_basepri;
extern  s_u32_t *m_taskmsg_psp;
#if MCUCFG_PENDSVFIFO_DEPTH > 0
extern  s_u32_t  mPendSV_FIFO_DepthMAX;
extern  void    *mPendSV_FIFO[2][MCUCFG_PENDSVFIFO_DEPTH + 1];
extern  void   **mPendSV_FIFO_P0;
extern  void   **mPendSV_FIFO_P1;
extern  void     mPendSV_FIFOLoader (void *sv);
extern  void     mPendSV_FIFOHandler(void);
#endif

/* PRAGMA */
#if __MCUCFG_WARNINGDISABLE
#pragma diag_suppress 177
#endif

/* CONST & ATTRIBUTE */
#define MCUCFG_ISA                __ARM__
#define MCUCFG_NOP                __NOP()
#define MCUCFG_PCLEN              4
#define MCUCFG_C51USING
#define MCUCFG_SYSTICK_ATTRIBUTE
#define MCUCFG_TERNARYMASK
/* TASKMSG */
#define MCUCFG_TASKMSG_TYPE       1
#define MCUCFG_TASKMSG_PSP        m_taskmsg_psp = (s_u32_t *)__m_get_psp()
#define MCUCFG_TASKMSG_SIZE       ((&m0 - &m0_ - 1) * 4)
#define MCUCFG_TASKMSG_VAR        m_taskmsg_t r0__, m_taskmsg_t r1__, m_taskmsg_t r2__, m_taskmsg_t r3__
#define MCUCFG_TASKMSG_VAL        0, 0, 0, 0

#if MCUCFG_ASPEN_LSPEN == __ENABLED__
#define MCUCFG_CALLER_PUSH_FPU    (18 * 4) /** \push   {s0-s15,FPSCR,UNKNOW} */
#define MCUCFG_CALLEE_PUSH_FPU    (16 * 4) /** \vstmdb {s16-s31} */
#else
#define MCUCFG_CALLER_PUSH_FPU    0
#define MCUCFG_CALLEE_PUSH_FPU    0
#endif
#define MCUCFG_CALLER_PUSH_REG    (8 * 4)  /** \push   {r0-r3,r12,r14(lr),r15(pc),xPSR} */
#define MCUCFG_CALLEE_PUSH_REG    (8 * 4)  /** \stmdb  {r4-r11} */
#define MCUCFG_CALLER_PUSH        (MCUCFG_CALLER_PUSH_FPU + MCUCFG_CALLER_PUSH_REG)
#define MCUCFG_CALLEE_PUSH        (MCUCFG_CALLEE_PUSH_FPU + MCUCFG_CALLEE_PUSH_REG)
#define MCUCFG_BASICSTACKSIZE     (MCUCFG_CALLER_PUSH + MCUCFG_CALLEE_PUSH)

#define MCUCFG_STACK_ALIGN        __align(8)
#define MCUCFG_TASKSTACK_REALLOC  __DISABLED__
#define MCUCFG_STACKSIZE_TASKMGR  (MCUCFG_BASICSTACKSIZE * 2 + 24)
#define MCUCFG_STACKSIZE_DEBUGGER (MCUCFG_BASICSTACKSIZE * 2)

/*
 * MCUAPI
 */

/* TaskNode */
#define mTaskNode_Head_           m_sp_t psp;
#define mTaskNode_Tail_           m_sp_t psp_top;

/* SysTick */
#define mSysTick_CLKMOD           (MCUCFG_SYSTICKCLKSOURCE ? 1 : 8)
#define mSysTick_Cycle            (SYSCFG_SYSCLK / (1000000UL / SYSCFG_SYSTICKCYCLE) / mSysTick_CLKMOD)
#if mSysTick_Cycle > 0x00FFFFFF
#error 系统滴答定时器溢出，必须减小系统时钟或系统滴答周期。
#elif 1000000UL % SYSCFG_SYSTICKCYCLE
#warning 每秒钟的系统滴答周期数不为整数，建议重新调整系统滴答周期。
#elif SYSCFG_SYSCLK % (1000000UL / SYSCFG_SYSTICKCYCLE)
#warning 每秒钟的系统滴答周期数不为整数，建议重新调整系统时钟或系统滴答周期。
#elif SYSCFG_SYSCLK / (1000000UL / SYSCFG_SYSTICKCYCLE) % mSysTick_CLKMOD
#warning 每秒钟的系统滴答周期数不为整数，建议重新调整系统时钟或系统滴答周期。
#endif
#define mSysTick_InitValue        mSysTick_Cycle
#define mSysTick_Counter          SysTick->VAL
#define mSysTick_CtrlReg          SysTick->CTRL = (MCUCFG_SYSTICKCLKSOURCE ? 0x04 : 0x00) | 0x01
#define mSysTick_Enable           SysTick->CTRL|= 0x02
#define mSysTick_Priority         *(volatile s_u8_t  *)0xE000ED23 = 0xFF
#define mSysTick_INIT \
do{ \
	SysTick->LOAD = mSysTick_InitValue; \
	mSysTick_Priority; \
	mSysTick_CtrlReg; \
}while(false)

/* 系统中断 */
#if !MCUCFG_SYSINT
/* 0、SysTick_Handler + PendSV_Handler */
#define mSysTick2_INIT            mSysTick_Enable
#define mPendSV_Priority          *(volatile s_u8_t  *)0xE000ED22 = 0xFF
#define mPendSV_Set               *(volatile s_u32_t *)0xE000ED04 = 0x10000000
#define mPendSV_Clear
#define mPendSV_INIT \
do{ \
	mPendSV_Priority; \
	m_basepri <<= 7 - ((*(volatile s_u32_t *)0xE000ED00 >> 8) & 7); \
	m_basepri--; \
	m_basepri <<= 1 + ((*(volatile s_u32_t *)0xE000ED00 >> 8) & 7); \
}while(false)
#define mSysIRQ_Disable           __mu_disable_sysirq()
#define mSysIRQ_Enable            __mx_resume_pri(0)
#else
/* 1、TIMn_IRQHandler + XXX_IRQHandler */
#define mSysTick2_Priority        *(volatile s_u32_t *)(0xE000E400 + MCUCFG_SYSTICKIRQ / 4 * 4)|= 0xFFUL << (MCUCFG_SYSTICKIRQ % 4) * 8
#define mPendSV_Priority          *(volatile s_u32_t *)(0xE000E400 + MCUCFG_PENDSVIRQ /  4 * 4)|= 0xFFUL << (MCUCFG_PENDSVIRQ %  4) * 8
#define mPendSV_Set               *(volatile s_u32_t *)(0xE000E200 + MCUCFG_PENDSVIRQ / 32 * 4) = 0x01UL << (MCUCFG_PENDSVIRQ % 32)/*
#define mPendSV_Clear             *(volatile s_u32_t *)(0xE000E280 + MCUCFG_PENDSVIRQ / 32 * 4) = 0x01UL << (MCUCFG_PENDSVIRQ % 32)*/
#define mPendSV_Clear
#define mPendSV_INIT \
do{ \
	mPendSV_Priority; \
	m_basepri = 1 + ((*(volatile s_u32_t *)0xE000ED00 >> 8) & 7); \
}while(false)
#define mSysINT_Disable           *(volatile s_u32_t *)(0xE000E180 + MCUCFG_PENDSVIRQ / 32 * 4) = (0x01UL << (MCUCFG_SYSTICKIRQ % 32)) \
                                                                                                | (0x01UL << (MCUCFG_PENDSVIRQ  % 32))
#define mSysINT_Enable            *(volatile s_u32_t *)(0xE000E100 + MCUCFG_PENDSVIRQ / 32 * 4) = (0x01UL << (MCUCFG_SYSTICKIRQ % 32)) \
                                                                                                | (0x01UL << (MCUCFG_PENDSVIRQ  % 32))
#define mSysIRQ_Disable           __mu_disable_sysirq()
#define mSysIRQ_Enable            __mu_enable_sysirq()
#endif

#define mxDisableIRQ              __mx_disable_irq()
#define mxMaskingPRI(newpri)      __mx_masking_pri(newpri)
#define mxResumeIRQ(oldirq)       __mx_resume_irq(oldirq)
#define mxResumePRI(oldpri)       __mx_resume_pri(oldpri)

#define mSys_Idle                 __WFI()

#if MCUCFG_HARDWAREFPU == __ENABLED__

#define mCPACR_Set \
do{ \
	*(volatile s_u32_t *)0xE000ED88 |= (0x0FUL << 20); \
	__asm("dsb"); \
}while(false) /*!< CPACR: CP11|CP10 */

#if MCUCFG_ASPEN_LSPEN == __ENABLED__

#define mFPCCR_Set \
do{ \
	*(volatile s_u32_t *)0xE000EF34 |= (0x03UL << 30); \
	__asm("isb"); \
}while(false) /*!< FPCCR: ASPEN|LSPEN */

#define mFPSCR_INIT \
do{ \
	*(volatile s_u32_t *)(node_news->psp - 8) = __m_get_fpscr(); \
}while(false) /*!< FPSCR */

#else

#define mFPCCR_Set \
do{ \
	*(volatile s_u32_t *)0xE000EF34 &=~(0x03UL << 30); \
	__asm("isb"); \
}while(false) /* FPCCR: ASPEN|LSPEN */

#define mFPSCR_INIT

#endif

#else
#define mCPACR_Set
#define mFPCCR_Set
#define mFPSCR_INIT
#endif

#define mSys_INIT \
do{ \
	__m_set_psp(__m_get_msp() - 2 * MCUCFG_BASICSTACKSIZE); \
	__m_set_control(0x02); \
	*(volatile s_u32_t *)0xE000ED14 |= 0x0200; /* 栈8字节对齐 */ \
	mCPACR_Set; \
	mFPCCR_Set; \
	mPendSV_INIT; \
	mSysTick_INIT; \
	mSysTick2_INIT; \
	mSysIRQ_Enable; \
	__asm("cpsie i"); \
}while(false)

#define mSysTick_Counting \
do{ \
	if(tick_temp <= mSysTick_Counter) break; \
	s_tick_counter1 += tick_temp - mSysTick_Counter; \
	s_tick_counter2++; \
}while(false)

#define mTaskStack_INIT \
do{ \
	node_news->psp_top = (m_sp_t)node_news->bsp + node_news->stacksize; \
	if(node_news->psp_top % 8){ \
		node_news->psp_top /= 8; \
		node_news->psp_top *= 8; \
		node_news->stacksize = node_news->psp_top - (m_sp_t)node_news->bsp; \
	} \
	node_news->psp = node_news->psp_top; \
	mFPSCR_INIT; /* FPSCR */ \
	*(volatile s_u32_t *)(node_news->psp - MCUCFG_CALLER_PUSH_FPU - 4) = 0x01000000; /* xPSR */ \
	*(volatile s_u32_t *)(node_news->psp - MCUCFG_CALLER_PUSH_FPU - 8) = (s_u32_t)s_task_starter->entry; /* r15(pc) */ \
	node_news->psp -= MCUCFG_BASICSTACKSIZE; \
}while(false)

#if SYSCFG_DEBUGGING == __ENABLED__
#define mTaskStack_LEN \
	s_taskstacklen = s_task_current->psp_top - __m_get_psp() + MCUCFG_CALLEE_PUSH
#endif

#define mUsedTime_END \
do{ \
	if(usedtime[0]){ \
		s_task_current->usedtime[0] += usedtime[0] - 1; \
		usedtime[0] = 0; \
		usedtime[1] += mSysTick_InitValue - tick_counter; \
	} \
	else if(tick_counter >= usedtime[1]){ \
		usedtime[0] = ~0; \
		usedtime[1] += mSysTick_InitValue - tick_counter; \
	} \
	else{ \
		usedtime[1] -= tick_counter; \
	} \
	s_task_current->usedtime[0] += (s_task_current->usedtime[1] + usedtime[1]) / mSysTick_Cycle; \
	s_task_current->usedtime[1]  = (s_task_current->usedtime[1] + usedtime[1]) % mSysTick_Cycle; \
}while(false)

#define mUsedTime_INIT \
do{ \
	usedtime[1] = tick_counter; \
}while(false)

#define mPendSV_FIFOLoad \
do{ \
	mPendSV_FIFOLoader(&u_psv); \
	mPendSV_Set; \
}while(false)

#define mPendSV_FIFOHandle \
	if(mPendSV_FIFO_P0 > mPendSV_FIFO[0]) mPendSV_FIFOHandler()

#define miWriteFlagBits \
	if(!u_psv.value){ \
		do{}while(false)

#define mUserReg_CSave
#define mUserReg_CRes



/*
 * STATIC INLINE
 */

__STATIC_INLINE s_u32_t __m_get_msp(void)
{
	register s_u32_t oldmsp;
	__asm("mrs oldmsp, msp");
	return oldmsp;
}

__STATIC_INLINE s_u32_t __m_get_psp(void)
{
	register s_u32_t oldpsp;
	__asm("mrs oldpsp, psp");
	return oldpsp;
}

__STATIC_INLINE void __m_set_psp(s_u32_t newpsp)
{
	__asm("msr psp, newpsp");
}

__STATIC_INLINE void __m_set_control(s_u32_t newctrl)
{
	__asm("msr control, newctrl");
}

__STATIC_INLINE s_u32_t __mx_disable_irq(void)
{
	register s_u32_t oldirq;
	__asm("mrs oldirq, primask");
	__asm("cpsid i");
	__asm("nop");
	return oldirq;
}

__STATIC_INLINE void __mx_resume_irq(s_u32_t oldirq)
{
	__asm("msr primask, oldirq");
}

#if !MCUCFG_SYSINT || MCUCFG_BASEPRI_USED
__STATIC_INLINE void __mx_resume_pri(s_u32_t oldpri)
{
	__asm("msr basepri, oldpri");
}
#endif

#if MCUCFG_SYSINT && MCUCFG_BASEPRI_USED
__STATIC_INLINE s_u32_t __mx_masking_pri(s_u32_t newpri)
{
	register s_u32_t oldpri;
	newpri <<= m_basepri;
	__asm("mrs oldpri, basepri");
	__asm("msr basepri_max, newpri");
	__asm("dsb");
	__asm("isb");
	return oldpri;
}
#endif

#if !MCUCFG_SYSINT
__STATIC_INLINE void __mu_disable_sysirq(void)
{
	__asm("msr basepri, m_basepri");
	__asm("dsb");
	__asm("isb");
}
#else
__STATIC_INLINE void __mu_enable_sysirq(void)
{
	mSysINT_Enable;
}

__STATIC_INLINE void __mu_disable_sysirq(void)
{
	mSysINT_Disable;
	__asm("dsb");
	__asm("isb");
}
#endif

#if MCUCFG_ASPEN_LSPEN == __ENABLED__
__STATIC_INLINE s_u32_t __m_get_fpscr(void)
{
	register s_u32_t oldfpscr;
	__asm("mrs oldfpscr, fpscr");
	return oldfpscr;
}
#endif



#endif
